ALMaSS  1.0
The Animal, Landscape and Man Simulation System
Pesticide Class Reference

#include <pesticide.h>

Public Member Functions

void Tick (void)
 
void DailyQueueAdd (LE *a_element_sprayed, double a_amount, PlantProtectionProducts a_ppp)
 
bool GetAnythingToDecay (PlantProtectionProducts a_ppp)
 
double SupplyPesticide (int a_x, int a_y, PlantProtectionProducts a_ppp)
 
double SupplyPesticide (int a_polyref, PlantProtectionProducts a_ppp)
 
 Pesticide (RasterMap *a_land, Landscape *a_map)
 
virtual ~Pesticide (void)
 
bool SavePPM (double *a_map, int a_beginx, int a_width, int a_beginy, int a_height, char *a_filename)
 
void DiffusionMaskInitTest (void)
 

Protected Member Functions

void DailyQueueClear (PlantProtectionProducts a_ppp)
 
void DailyQueueProcess (PlantProtectionProducts a_ppp)
 
bool ElementIsWater (int a_x, int a_y)
 
void MainMapDecay (PlantProtectionProducts a_ppp)
 
void TwinMapClear (int a_minx, int a_miny, int a_maxx, int a_maxy)
 
void TwinMapSpray (LE *a_element_spryaed, double a_amount, int a_minx, int a_miny, int a_maxx, int a_maxy)
 
void TwinMapSprayPixel (int a_large_map_x, int a_large_map_y, double a_fractional_amount)
 
void TwinMapSprayCorrectBorders (void)
 
void TwinMapDiffusion (int a_minx, int a_miny, int a_maxx, int a_maxy, double a_cover, PlantProtectionProducts a_ppp)
 
void DiffusionMaskInit (void)
 
double DiffusionFunction (double a_dist_meters)
 
void DiffusionSprayPixel (int a_x, int a_limit_x, int a_y, int a_limit_y, double a_amount, double a_cover, PlantProtectionProducts a_ppp)
 
void CalcRainWashOffFactors ()
 Pre-calculates the constants required for rain wash off with increasing rainfall and stores this in m_RainWashoffFactor. More...
 

Protected Attributes

bool m_something_to_decay [ppp_foobar]
 Speed hack. Only actually run the daily decay routine on the pesticide map if and only if we are sure that there is some pesticide anywhere on the map for us to process. More...
 
int m_NoPPPs
 The number of active PPPs to track. More...
 
int m_x_excess
 
int m_y_excess
 
double m_prop
 
double m_corr_x
 
double m_corr_y
 
int m_wind
 
double m_pest_daily_decay_frac
 
double m_pest_daily_decay_frac_Veg
 
double m_pest_daily_decay_frac_Soil
 
RasterMapm_land
 
Landscapem_map
 
vector< vector< double > > m_pest_map_main
 
double * m_pest_map_twin
 The complete pesticide map. More...
 
unsigned int m_pest_map_size
 The total size of one map in cellsize resolution. More...
 
unsigned int m_pest_map_width
 The width of one map in cellsize resolution. More...
 
unsigned int m_pest_map_height
 The height of one map in cellsize resolution. More...
 
double m_RainWashoffFactor [10000]
 a structure to hold pre-calculated pesticide rain wash off factor (Rw) More...
 
unsigned m_rainfallcategory
 Daily rainfall saved here * 100 to use as an index to the Pesticide::m_RainWashoffFactor array - an optimisation to stop repeated calls to Landscape::SupplyRain. More...
 
Diffusion_mask m_diffusion_mask [4]
 Pre-calculated square diffusion map, assuming wind directions (4)
Used after spraying an element in the pesticide map to determine how much of the sprayed material spreads into the surroundings. More...
 
vector< vector< PesticideEvent * > > m_daily_spray_queue
 List lists of landscape elements, which was sprayed on a given day. One for each PPP we track. More...
 

Constructor & Destructor Documentation

◆ Pesticide()

Pesticide::Pesticide ( RasterMap a_land,
Landscape a_map 
)

First determine the size of the maps we need in terms of the number of PPPs to track

For vegetation fraction, the decay is based on ln(2)/DT50

For soil fraction, the decay is based on 10^(log10(0.5) /DT50)

527 {
529  {
532  m_map = a_map;
533  m_land = a_land;
534  for (int i=0; i< m_NoPPPs; i++) m_something_to_decay[i] = false;
536 
537  // Figure out critical border coordinates,
538  // proportional fractions etc.
539  m_prop = 1.0 / ((double)(PEST_GRIDAREA));
541  if ( m_x_excess ) {
542  m_corr_x = (double)PEST_GRIDSIZE /(double)m_x_excess;
543  }
545  if ( m_y_excess ) {
546  m_corr_y = (double)PEST_GRIDSIZE / (double)m_y_excess;
547  }
548 
549  m_pest_map_width = m_land->MapWidth() >> PEST_GRIDSIZE_POW2; // landscape width divided by the sqrt(cellsize) e.g. cellsize 4 and landscape width = 10000, result is 10000/(sqrt(4) = 5000
550  if ( m_land->MapWidth() & (PEST_GRIDSIZE-1))
552 
554  if ( m_land->MapHeight() & (PEST_GRIDSIZE-1))
556 
558 
559  m_pest_map_twin = new double[m_pest_map_size];
560 #ifdef __DETAILED_PESTICIDE_FATE
561  m_pest_map_vegcanopy.resize(m_NoPPPs);
562  m_pest_map_soil.resize(m_NoPPPs);
563 #else
564  m_pest_map_main.resize(m_NoPPPs);
565 #endif
566  for (int p = 0; p < m_NoPPPs; p++) {
567 #ifdef __DETAILED_PESTICIDE_FATE
568  m_pest_map_vegcanopy[p].resize(m_pest_map_size);
569  m_pest_map_soil[p].resize(m_pest_map_size);
570  fill(m_pest_map_vegcanopy[p].begin(), m_pest_map_vegcanopy[p].end(), 0.0);
571  fill(m_pest_map_soil[p].begin(), m_pest_map_soil[p].end(), 0.0);
572 #else
573  m_pest_map_main[p].resize(m_pest_map_size);
574  fill(m_pest_map_main[p].begin(), m_pest_map_main[p].end(), 0.0);
575 
576 #endif
577  m_daily_spray_queue[p].resize(0);
578  }
579 
580  for (unsigned int i = 0; i < m_pest_map_size; i++) m_pest_map_twin[i] = 0.0;
581 
582  m_pest_daily_decay_frac = pow(10.0, log10(0.5) / l_pest_ai_half_life.value());
584 #ifdef __BORLANDC__
586 #else
588 #endif
590  m_pest_daily_decay_frac_Soil = pow(10.0, log10(0.5) / l_pest_ai_half_life_Soil.value());
591  // This calculates
595  }
596 }
bool value(void)
Definition: configurator.h:135
double value(void)
Definition: configurator.h:118
int value(void)
Definition: configurator.h:98
double m_corr_y
Definition: pesticide.h:158
double m_pest_daily_decay_frac_Soil
Definition: pesticide.h:165
void DiffusionMaskInit(void)
Definition: pesticide.cpp:325
double m_pest_daily_decay_frac
Definition: pesticide.h:163
double m_pest_daily_decay_frac_Veg
Definition: pesticide.h:164
void CalcRainWashOffFactors()
Pre-calculates the constants required for rain wash off with increasing rainfall and stores this in m...
Definition: pesticide.cpp:599
int m_NoPPPs
The number of active PPPs to track.
Definition: pesticide.h:149
unsigned int m_pest_map_height
The height of one map in cellsize resolution.
Definition: pesticide.h:188
double m_prop
Definition: pesticide.h:156
unsigned int m_pest_map_width
The width of one map in cellsize resolution.
Definition: pesticide.h:186
RasterMap * m_land
Definition: pesticide.h:168
int m_x_excess
Definition: pesticide.h:154
void DiffusionMaskInitTest(void)
Definition: pesticide.cpp:640
vector< vector< double > > m_pest_map_main
Definition: pesticide.h:179
bool m_something_to_decay[ppp_foobar]
Speed hack. Only actually run the daily decay routine on the pesticide map if and only if we are sure...
Definition: pesticide.h:146
unsigned int m_pest_map_size
The total size of one map in cellsize resolution.
Definition: pesticide.h:184
int m_y_excess
Definition: pesticide.h:155
vector< vector< PesticideEvent * > > m_daily_spray_queue
List lists of landscape elements, which was sprayed on a given day. One for each PPP we track.
Definition: pesticide.h:200
Landscape * m_map
Definition: pesticide.h:171
double * m_pest_map_twin
The complete pesticide map.
Definition: pesticide.h:182
double m_corr_x
Definition: pesticide.h:157
int MapWidth(void)
Definition: rastermap.h:52
int MapHeight(void)
Definition: rastermap.h:53
static CfgFloat l_pest_ai_half_life_Soil("PEST_AI_HALF_LIFE_SOIL", CFG_CUSTOM, 10.0)
CfgInt l_pest_NoPPPs("PEST_NO_OF_PPPS", CFG_CUSTOM, 1, 1, 10)
The number of active Plant Protection Products to be tracked - a performance penalty if enabled with ...
CfgBool l_pest_enable_pesticide_engine("PEST_ENABLE_PESTICIDE_ENGINE", CFG_CUSTOM, false)
Used to turn on or off the PPP functionality of ALMaSS.
static CfgFloat l_pest_ai_half_life_Veg("PEST_AI_HALF_LIFE_VEG", CFG_CUSTOM, 10.0)
static CfgFloat l_pest_ai_half_life("PEST_AI_HALF_LIFE", CFG_CUSTOM, 10.0)
#define PEST_GRIDSIZE_POW2
Definition: pesticide.h:39
#define PEST_GRIDAREA
Definition: pesticide.h:41
#define PEST_GRIDSIZE
Definition: pesticide.h:40

References CalcRainWashOffFactors(), DiffusionMaskInit(), DiffusionMaskInitTest(), l_pest_ai_half_life, l_pest_ai_half_life_Soil, l_pest_ai_half_life_Veg, l_pest_enable_pesticide_engine, l_pest_NoPPPs, m_corr_x, m_corr_y, m_daily_spray_queue, m_land, m_map, m_NoPPPs, m_pest_daily_decay_frac, m_pest_daily_decay_frac_Soil, m_pest_daily_decay_frac_Veg, m_pest_map_height, m_pest_map_main, m_pest_map_size, m_pest_map_twin, m_pest_map_width, m_prop, m_something_to_decay, m_x_excess, m_y_excess, RasterMap::MapHeight(), RasterMap::MapWidth(), PEST_GRIDAREA, PEST_GRIDSIZE, PEST_GRIDSIZE_POW2, CfgInt::value(), CfgFloat::value(), and CfgBool::value().

◆ ~Pesticide()

Pesticide::~Pesticide ( void  )
virtual
622 {
624  {
625  for (int winddir = 0; winddir < 4; winddir++)
626  {
627  for (unsigned int i = 0; i < m_diffusion_mask[winddir].size(); i++)
628  {
629  delete m_diffusion_mask[winddir][i];
630  }
631  m_diffusion_mask[winddir].resize(0);
632  }
633  delete m_pest_map_twin;
634  }
635 }
Diffusion_mask m_diffusion_mask[4]
Pre-calculated square diffusion map, assuming wind directions (4) Used after spraying an element in...
Definition: pesticide.h:197

References l_pest_enable_pesticide_engine, m_diffusion_mask, m_pest_map_twin, and CfgBool::value().

Member Function Documentation

◆ CalcRainWashOffFactors()

void Pesticide::CalcRainWashOffFactors ( )
protected

Pre-calculates the constants required for rain wash off with increasing rainfall and stores this in m_RainWashoffFactor.

Calculates the proportion of pesticide that is washed off the canopy for 0.1 to 10mm of rain and for 0 to 100% cover in 1% steps.

600 {
604  double rainsteps = 0.1; // mm, multiply rainfall by 100 to get this, save result as integer
605  double coversteps = 1.0; // %, multiply cover by 100 to get this, save result as integer
606  for (int i = 0; i < 100; i++)
607  {
608  double SC = i * coversteps;
609  double LAI = log(0 - (1 - SC))*1.666666667; // This is the inverse of Beer's Law
610  for (int r = 0; r < 100; r++)
611  {
612  double P = r * rainsteps;
613  double Pi = LAI*(1 - (1 / ((1 + SC * P) / LAI)));
614  double Rw = 0.25*(SC * P - Pi); // Rw is a proportion of canopy pesticide washed off.
615  m_RainWashoffFactor[r * 100 + i] = Rw;
616  }
617  }
618 }
double m_RainWashoffFactor[10000]
a structure to hold pre-calculated pesticide rain wash off factor (Rw)
Definition: pesticide.h:191

References m_RainWashoffFactor.

Referenced by Pesticide().

◆ DailyQueueAdd()

void Pesticide::DailyQueueAdd ( LE a_element_sprayed,
double  a_amount,
PlantProtectionProducts  a_ppp 
)
141 {
142  PesticideEvent *l_event = new PesticideEvent( a_element_sprayed, a_amount, a_ppp );
143  m_daily_spray_queue[a_ppp].push_back(l_event);
144 }
Definition: pesticide.h:62

References m_daily_spray_queue.

Referenced by Orchard::DoDevelopment(), OrchardBand::DoDevelopment(), Farm::ProductApplication(), and Farm::ProductApplication_DateLimited().

◆ DailyQueueClear()

void Pesticide::DailyQueueClear ( PlantProtectionProducts  a_ppp)
protected

Empties and resets the pesticide action queue. On calling any event not yet carried out will be deleted.

132 {
136  if (! m_daily_spray_queue[a_ppp].empty()) m_daily_spray_queue[a_ppp].resize( 0 );
137 }

References m_daily_spray_queue.

Referenced by Tick().

◆ DailyQueueProcess()

void Pesticide::DailyQueueProcess ( PlantProtectionProducts  a_ppp)
protected

If we are spraying at least one field. Force the main pesticide map which forces the decay method to run tomorrow. First we add the amount in m_amount to the twin map (all squares covered with the polygon get m_amount added) using TwinMapSpray
Next this twin map is added to the main map and if necessary it is here we sort out the allocation between vegetation canopy and soil fractions. This is done by TwinMapDiffusion

148 {
155  if (0 == m_daily_spray_queue[a_ppp].size())
156  // Event queue empty, nobody sprayed anything today.
157  return;
158 
159  // Spraying at least one field. Force the main pesticide map
160  // decay method to run tomorrow.
161  m_something_to_decay[a_ppp] = true;
162 
163  for ( unsigned int i=0; i<m_daily_spray_queue[a_ppp].size(); i++ )
164  {
166  int minx=m_daily_spray_queue[a_ppp][i]->m_sprayed_elem->GetMinX();
167  int maxx=m_daily_spray_queue[a_ppp][i]->m_sprayed_elem->GetMaxX();
168  int miny=m_daily_spray_queue[a_ppp][i]->m_sprayed_elem->GetMinY();
169  int maxy=m_daily_spray_queue[a_ppp][i]->m_sprayed_elem->GetMaxY();
170  // For cover we use the crop, and save this for later
171  double cover = m_daily_spray_queue[a_ppp][i]->m_sprayed_elem->GetVegCover();
172  TwinMapClear(minx, miny, maxx, maxy);
173  // Add the amount in m_amount to the twin map (all squares covered with the polygon get m_amount added.
174  TwinMapSpray( m_daily_spray_queue[a_ppp][i]->m_sprayed_elem, m_daily_spray_queue[a_ppp][i]->m_amount, minx, miny, maxx, maxy);
175  // This adds it to the main map and if necessary sorts out the allocation between veg and soil.
176  TwinMapDiffusion(minx, miny, maxx, maxy, cover, a_ppp);
177  }
178 }
int SupplyWindDirection(void)
Definition: landscape.h:1423
void TwinMapSpray(LE *a_element_spryaed, double a_amount, int a_minx, int a_miny, int a_maxx, int a_maxy)
Definition: pesticide.cpp:194
void TwinMapDiffusion(int a_minx, int a_miny, int a_maxx, int a_maxy, double a_cover, PlantProtectionProducts a_ppp)
Definition: pesticide.cpp:276
int m_wind
Definition: pesticide.h:159
void TwinMapClear(int a_minx, int a_miny, int a_maxx, int a_maxy)
Definition: pesticide.cpp:181
Landscape * g_land
Definition: skylarks_all.cpp:49

References g_land, m_daily_spray_queue, m_something_to_decay, m_wind, Landscape::SupplyWindDirection(), TwinMapClear(), TwinMapDiffusion(), and TwinMapSpray().

Referenced by Tick().

◆ DiffusionFunction()

double Pesticide::DiffusionFunction ( double  a_dist_meters)
protected

The equation provided here is the one that determines the drift of pesticides with distance. It is important that if the drift is set to zero that the result of the equation is unity.

443 {
444  double pp;
449 // y=(2.753767)*(x+(1.86976))**(-2.121563)
450 #ifdef __WithinOrchardPesticideSim__
451  if (a_dist_meters==0) pp=0.7784;
452  else pp=0.0277;
453 #else
454  //pp = (2.7705 * pow(a_dist_meters, -0.9787)) * 0.01; // german drif equation (reference)
455  pp = (2.7705 * pow(a_dist_meters, -1.7)) * 0.01; // german drif equation - reduction of drift by 50%
456  //pp = (2.7705 * pow(a_dist_meters, -2.5)) * 0.01; // german drif equation - reduction of drift by 75%
457  //pp = (2.7705 * pow(a_dist_meters, -3.5)) * 0.01; // german drif equation - reduction of drift by 90%
458 
459  //pp=2.753767 * pow(( a_dist_meters+1.86976 ), -2.121563); // based on drift data from the spray drift calculator within FOCUS's surface water scenarios SWASH software (FOCUS, 2001)
460  //pp= exp( l_pest_diffusion_slope.value() * a_dist_meters );
461  pp=pow(( a_dist_meters+1 ), l_pest_diffusion_slope.value() );
462  //pp = (2.7593 * pow(a_dist_meters,-0.9778)) * 0.001;
463  if (pp<(l_pest_zero_threshold.value()/10)) pp=0; // Don't bother with the little ones
464 #endif
465  return pp;
466 }
static CfgFloat l_pest_zero_threshold("PEST_ZERO_THRESHOLD", CFG_CUSTOM, 0.00001)
static CfgFloat l_pest_diffusion_slope("PEST_DRIFT_SLOPE", CFG_CUSTOM, -0.6122)

References l_pest_diffusion_slope, l_pest_zero_threshold, and CfgFloat::value().

Referenced by DiffusionMaskInit().

◆ DiffusionMaskInit()

void Pesticide::DiffusionMaskInit ( void  )
protected

l_pest_diffusion_grid_count contains the number of grid points to consider e.g. 1 will be a grid of 9 squares centred at the spray point, 2 will be 25 squares (2*2+1)^2 , 3 will be 49, etc..
The proportion of the applicationcation rate assuming it was sprayed in the centre square is calculated for each surrounding square. Wind direction is taken into account and the mask is created for four wind directions and saved.

326 {
334  int l_grid = l_pest_diffusion_grid_count.value();
335  const int l_side_length = l_grid * 2 + 1;
336  double* l_diff;
337  l_diff = new double[l_side_length];
338  int cells = 1;
339  double sum = 1.0;
340  l_diff[0] = 1.0;
341  for (int l=1; l<l_side_length; l++)
342  {
343  l_diff[l] = DiffusionFunction(l);
344  sum += l_diff[l];
345  }
346  for (int l=0; l<l_side_length; l++)
347  {
348  l_diff[l] /= sum;
349  l_diff[l] /= cells;
350  cells += 2; // 2 more cells per row away from centre square
351  }
352  // Calculated for 4 wind directions
353  for (int wind=0; wind < 4; wind ++)
354  {
355  m_diffusion_mask[wind].resize( l_side_length * l_side_length );
356  for ( int x = 0; x< l_side_length; x++ )
357  {
358  for ( int y= 0; y< l_side_length; y++ )
359  {
360  m_diffusion_mask[wind][x + y * l_side_length] = new Diffusor( x, y, 0); // first zero all values
361  }
362  }
363  }
364  int strtx = l_grid;
365  int strty = l_grid;
366  int fin = 1;
367  // North
368  for (int step = 0; step <= l_grid; step++)
369  {
370  for (int cc=0; cc<fin; cc++)
371  {
372  m_diffusion_mask[0][ strtx + (cc-step) + ((strty-step)*l_side_length)]->SetFraction(l_diff[step]);
373  }
374  fin += 2;
375  }
376  // South
377  fin = 1;
378  for (int step = 0; step <= l_grid; step++)
379  {
380  for (int cc=0; cc<fin; cc++)
381  {
382  m_diffusion_mask[2][ strtx + (cc-step) + ((strty+step)*l_side_length)]->SetFraction(l_diff[step]);
383  }
384  fin += 2;
385  }
386  // East
387  fin = 1;
388  for (int step = 0; step <= l_grid; step++)
389  {
390  for (int cc=0; cc<fin; cc++)
391  {
392  m_diffusion_mask[3][ (strtx + step) + ((strty+(cc-step))*l_side_length)]->SetFraction(l_diff[step]);
393  }
394  fin += 2;
395  }
396  // West
397  fin = 1;
398  for (int step = 0; step <= l_grid; step++)
399  {
400  for (int cc=0; cc<fin; cc++)
401  {
402  m_diffusion_mask[1][ (strtx - step) + ((strty+(cc-step))*l_side_length)]->SetFraction(l_diff[step]);
403  }
404  fin += 2;
405  }
406 
407  delete[] l_diff;
408 }
Definition: pesticide.h:78
double DiffusionFunction(double a_dist_meters)
Definition: pesticide.cpp:442
static CfgInt l_pest_diffusion_grid_count("PEST_DIFFUSION_GRID_COUNT", CFG_CUSTOM, 1)

References DiffusionFunction(), l_pest_diffusion_grid_count, m_diffusion_mask, and CfgInt::value().

Referenced by Pesticide().

◆ DiffusionMaskInitTest()

void Pesticide::DiffusionMaskInitTest ( void  )
641 {
642  int l_grid = l_pest_diffusion_grid_count.value();
643  const int l_side_length = l_grid * 2 + 1;
644 
645  // Need a debug test, output all diffusion masks to file
646  ofstream ofile("diffusionmask.txt",ios::out);
647  for (int i=0; i<4; i++)
648  {
649  for ( int x = 0; x< l_side_length; x++ )
650  {
651  for ( int y= 0; y< l_side_length; y++ )
652  {
653  ofile << m_diffusion_mask[i][x+(y*l_side_length)]->GetFraction() << '\t';
654  }
655  ofile << endl;
656  }
657  ofile << endl;
658  ofile << endl;
659  }
660  ofile.close();
661  }

References l_pest_diffusion_grid_count, m_diffusion_mask, and CfgInt::value().

Referenced by Pesticide().

◆ DiffusionSprayPixel()

void Pesticide::DiffusionSprayPixel ( int  a_x,
int  a_limit_x,
int  a_y,
int  a_limit_y,
double  a_amount,
double  a_cover,
PlantProtectionProducts  a_ppp 
)
inlineprotected

This sprays the pesticide (a_amount) by placing this into a pesticide cell in the main map. If more detailed pesticide fate is needed then a_amount will be partitioned between soil and canopy.
First a test is made to ensure that the coordinates given are within the landscape. If not the pesticide is sprayed off world, and lost.
Partioning, if occuring, is done based on two components - the canopy and the soil. The pesticide is partioned between the two based on the asssumed vegetation cover of the crop based on Beer's Law.

303 {
311  // First we have to do the typical out of bounds checks - if these fail do nothing, the pesticide fell off the world
312  if (a_x < 0 || a_x >= a_limit_x || a_y < 0 || a_y >= a_limit_y) return;
313  // Now calculate the coordinate entry in the array and store this as l_coord
314  int l_coord = a_y * a_limit_x + a_x;
315 #ifdef __DETAILED_PESTICIDE_FATE
316  // Here we need to calculate the partition of pesticide into two compartments.
317  m_pest_map_vegcanopy[a_ppp][l_coord] += a_amount * a_cover;
318  m_pest_map_soil[a_ppp][l_coord] += a_amount - m_pest_map_vegcanopy[a_ppp][l_coord];
319 #else
320  m_pest_map_main[a_ppp][l_coord] += a_amount;
321 #endif
322 }

References m_pest_map_main.

Referenced by TwinMapDiffusion().

◆ ElementIsWater()

bool Pesticide::ElementIsWater ( int  a_x,
int  a_y 
)
inlineprotected
264 {
265  TTypesOfLandscapeElement l_eletype =
266  m_map->SupplyElementType( a_x, a_y );
267 
268  if ( l_eletype == tole_Freshwater ||
269  l_eletype == tole_River ||
270  l_eletype == tole_Pond ||
271  l_eletype == tole_FishFarm ||
272  l_eletype == tole_Saltwater
273  )
274  return true;
275 
276  return false;
277 }
TTypesOfLandscapeElement SupplyElementType(int a_polyref)
Definition: landscape.h:1110
TTypesOfLandscapeElement
Definition: tole_declaration.h:36
@ tole_Saltwater
Definition: tole_declaration.h:66
@ tole_River
Definition: tole_declaration.h:65
@ tole_Pond
Definition: tole_declaration.h:101
@ tole_Freshwater
Definition: tole_declaration.h:64
@ tole_FishFarm
Definition: tole_declaration.h:102

References m_map, Landscape::SupplyElementType(), tole_FishFarm, tole_Freshwater, tole_Pond, tole_River, and tole_Saltwater.

Referenced by SupplyPesticide().

◆ GetAnythingToDecay()

bool Pesticide::GetAnythingToDecay ( PlantProtectionProducts  a_ppp)
inline
228 { return (m_something_to_decay[a_ppp]); }

References m_something_to_decay.

Referenced by Landscape::SupplyPesticideDecay().

◆ MainMapDecay()

void Pesticide::MainMapDecay ( PlantProtectionProducts  a_ppp)
protected

This is where the environmental decay takes place. Here we assume a first order decay based on a daily proportion of the cell total. If using detailed fate modelling then is calculation is more complex.

This is where the environmental decay takes place. Here we assume a first order decay based on a daily proportion of the cell total. If using detailed fate modelling then is calculation is more complex.

470 {
471  if ( ! m_something_to_decay[a_ppp] ) return;
476  double l_zero = l_pest_zero_threshold.value();
477  m_something_to_decay[a_ppp] = false;
478  for ( unsigned int i=0; i<m_pest_map_size; i++ )
479  {
480 #ifdef __DETAILED_PESTICIDE_FATE
481  if ((m_pest_map_vegcanopy[a_ppp][i] > l_zero) )
482  {
483  //Calculate wash-off m_pest_map_width * m_pest_map_height y * m_pest_map_width + x
484  int x = ( i % m_pest_map_width ) << PEST_GRIDSIZE_POW2;
485  int y = ( i / m_pest_map_width ) << PEST_GRIDSIZE_POW2;
486  double cover = g_landscape_p->SupplyVegCover(x,y);
487  unsigned cov = 100 * cover; // Cover is steps of zero to 99, may need to check for bounds here (may get cover of 1.0 ?)
488  double Rwp = m_pest_map_vegcanopy[a_ppp][i] *= m_RainWashoffFactor[m_rainfallcategory+cov]; // m_RainWashoffFactor is the index to the array
489  m_pest_map_soil[a_ppp][i] = (m_pest_map_soil[a_ppp][i] + Rwp) * m_pest_daily_decay_frac_Soil;
490  m_pest_map_vegcanopy[a_ppp][i] -= Rwp;
491  m_pest_map_vegcanopy[a_ppp][i] *= m_pest_daily_decay_frac_Veg;
492  m_something_to_decay[a_ppp] = true;
493  }
494  else
495  {
496  if (m_pest_map_soil[a_ppp][i] > l_zero)
497  {
498  m_pest_map_soil[a_ppp][i] = m_pest_map_soil[a_ppp][i] * m_pest_daily_decay_frac_Soil;
499  m_something_to_decay[a_ppp] = true;
500  }
501  else
502  {
503  m_pest_map_vegcanopy[a_ppp][i] = 0.0;
504  m_pest_map_soil[a_ppp][i] = 0.0;
505  }
506  }
507 #else
508  if (m_pest_map_main[a_ppp][i] > l_zero)
509  {
515  m_something_to_decay[a_ppp] = true;
516  }
517  else
518  {
519  m_pest_map_main[a_ppp][i] = 0.0;
520  }
521 #endif
522  }
523 }
double SupplyVegCover(int a_polyref)
Definition: landscape.h:1048
unsigned m_rainfallcategory
Daily rainfall saved here * 100 to use as an index to the Pesticide::m_RainWashoffFactor array - an o...
Definition: pesticide.h:193
class Landscape * g_landscape_p
Definition: Landscape.cpp:258

References g_landscape_p, l_pest_zero_threshold, m_pest_daily_decay_frac, m_pest_daily_decay_frac_Soil, m_pest_daily_decay_frac_Veg, m_pest_map_main, m_pest_map_size, m_pest_map_width, m_rainfallcategory, m_RainWashoffFactor, m_something_to_decay, PEST_GRIDSIZE_POW2, Landscape::SupplyVegCover(), and CfgFloat::value().

Referenced by Tick().

◆ SavePPM()

bool Pesticide::SavePPM ( double *  a_map,
int  a_beginx,
int  a_width,
int  a_beginy,
int  a_height,
char *  a_filename 
)
677 {
678  a_beginx = 0;
679  a_width = m_pest_map_width;
680  a_beginy = 0;
681  a_height = m_pest_map_height;
682 
683  SV_UINT32 linesize = a_width*3;
684  SV_UINT8* linebuffer = (SV_UINT8*)malloc(sizeof(SV_UINT8)* linesize);
685 
686  if ( linebuffer == NULL ) {
688  "Pesticide::SavePPM(): Out of memory!", "" );
689  exit(1);
690  }
691 
692  FILE* l_file;
693  l_file=fopen(a_filename, "w" );
694  if ( !l_file ) {
695  printf("PesticideTest::SavePPM(): "
696  "Unable to open file for writing: %s\n",
697  a_filename );
698  exit(1);
699  }
700 
701  fprintf( l_file, "P6\n%d %d %d\n",
702  a_width,
703  a_height,
704  255 );
705 
706  for ( int line=a_beginy; line< a_beginy + a_height; line++ ) {
707  int i = 0;
708  for ( int column=a_beginx; column < a_beginx + a_width; column++ ) {
709  int localcolor = (int)( a_map[ line * m_pest_map_width + column ]
710  * 255.0);
711  if ( localcolor <= 255 ) {
712  linebuffer [ i++ ] = char (localcolor & 0xff);
713  linebuffer [ i++ ] = 0;
714  linebuffer [ i++ ] = 0;
715  } else {
716  linebuffer [ i++ ] = 255;
717  localcolor -= 255;
718  if ( localcolor <= 255 ) {
719  linebuffer [ i++ ] = char (localcolor);
720  linebuffer [ i++ ] = 0;
721  } else {
722  linebuffer [ i++ ] = 255;
723  localcolor -= 255;
724  if ( localcolor <= 255 ) {
725  linebuffer [ i++ ] = char (localcolor);
726  } else {
727  linebuffer [ i++ ] = 255;
728  }
729  }
730  }
731  }
732  fwrite( linebuffer, sizeof(SV_UINT8), linesize, l_file );
733  }
734 
735  fclose( l_file );
736  free( linebuffer );
737  return true;
738 }
void Warn(MapErrorState a_level, std::string a_msg1, std::string a_msg2)
Definition: maperrormsg.cpp:59
class MapErrorMsg * g_msg
This pointer provides access the to the internal ALMaSS error message system.
Definition: maperrormsg.cpp:41
@ WARN_FATAL
Definition: maperrormsg.h:35
#define SV_UINT32
Definition: pesticide.cpp:668
#define SV_UINT8
Definition: pesticide.cpp:670

References g_msg, m_pest_map_height, m_pest_map_width, SV_UINT32, SV_UINT8, MapErrorMsg::Warn(), and WARN_FATAL.

◆ SupplyPesticide() [1/2]

double Pesticide::SupplyPesticide ( int  a_polyref,
PlantProtectionProducts  a_ppp 
)
inline
348 {
349  // This is an approximation because we have no idea about the actual variation
350  // in pesticide concentrations within the polygon.
351  int l_c = m_map->SupplyPesticideCell(a_ele);
352  return m_pest_map_main[a_ppp][l_c];
353 }
int SupplyPesticideCell(int a_polyref)
Definition: landscape.h:1468

References m_map, m_pest_map_main, and Landscape::SupplyPesticideCell().

◆ SupplyPesticide() [2/2]

double Pesticide::SupplyPesticide ( int  a_x,
int  a_y,
PlantProtectionProducts  a_ppp 
)
inline
Parameters
a_xthe x-coord in landscape x units
a_ythe y-coord in landscape x units
Returns
Returns the value of the pesticide grid cell containing a_x,a_y
330 {
336 #ifdef PEST_WATER_CHECK
337  if (ElementIsWater(a_x, a_y))
338  return 0.0;
339 #endif
340 
341  int l_x = a_x >> PEST_GRIDSIZE_POW2;
342  int l_y = a_y >> PEST_GRIDSIZE_POW2;
343 
344  return m_pest_map_main[a_ppp][l_y * m_pest_map_width + l_x];
345 }
bool ElementIsWater(int a_x, int a_y)
Definition: pesticide.h:263

References ElementIsWater(), m_pest_map_main, m_pest_map_width, and PEST_GRIDSIZE_POW2.

Referenced by Landscape::SupplyPesticide(), Landscape::SupplyPesticideP(), and Landscape::SupplyPesticideS().

◆ Tick()

void Pesticide::Tick ( void  )
98 {
100  {
101  return;
102  }
103  // Calculate DT50 rates
104  // DT50 will change by the rate of 0.22 extra per degree different from 20
105  double temp = g_weather->GetTemp();
106  double Dt50 = l_pest_ai_half_life.value()* exp(0.094779*(20 - temp));
107 
108  m_pest_daily_decay_frac = pow(10.0, log10(0.5) / Dt50);
109  // Get todays rainfall
110  m_rainfallcategory = (unsigned)floor(g_land->SupplyRain() * 100 + 0.5);
111  if (m_rainfallcategory >= 100) m_rainfallcategory = 99;
112  // Now make it an index to the 100x100 array.
113  m_rainfallcategory *= 100;
115  {
116  for (int ppp = ppp_1; ppp < m_NoPPPs; ppp++)
117  {
119  }
120  return;
121  }
122  for (int ppp = ppp_1; ppp < m_NoPPPs; ppp++)
123  {
127  }
128 }
double SupplyRain(void)
Definition: landscape.h:1365
void DailyQueueProcess(PlantProtectionProducts a_ppp)
Definition: pesticide.cpp:147
void DailyQueueClear(PlantProtectionProducts a_ppp)
Definition: pesticide.cpp:131
void MainMapDecay(PlantProtectionProducts a_ppp)
Definition: pesticide.cpp:469
double GetTemp(long a_date)
Get the temperature on a particular date.
Definition: weather.h:417
PlantProtectionProducts
A list PPP names for tracking by the Pesticide class.
Definition: farm.h:421
@ ppp_1
Definition: farm.h:422
class Weather * g_weather
Definition: weather.cpp:41

References DailyQueueClear(), DailyQueueProcess(), g_land, g_weather, Weather::GetTemp(), l_pest_ai_half_life, l_pest_enable_pesticide_engine, m_NoPPPs, m_pest_daily_decay_frac, m_rainfallcategory, MainMapDecay(), ppp_1, Landscape::SupplyRain(), CfgFloat::value(), and CfgBool::value().

Referenced by Landscape::Tick().

◆ TwinMapClear()

void Pesticide::TwinMapClear ( int  a_minx,
int  a_miny,
int  a_maxx,
int  a_maxy 
)
protected
182 {
183  for ( int y=a_miny; y<=a_maxy; y++ )
184  {
185  int t = y * m_pest_map_width;
186  for ( int x=a_minx; x<=a_maxx; x++ )
187  {
188  m_pest_map_twin[t + x] = 0.0;
189  }
190  }
191 }

References m_pest_map_twin, and m_pest_map_width.

Referenced by DailyQueueProcess().

◆ TwinMapDiffusion()

void Pesticide::TwinMapDiffusion ( int  a_minx,
int  a_miny,
int  a_maxx,
int  a_maxy,
double  a_cover,
PlantProtectionProducts  a_ppp 
)
protected
277 {
278  for ( int y=a_miny; y<a_maxy; y++ )
279  {
280  int t = y*m_pest_map_width;
281  for ( int x=a_minx; x<a_maxx; x++ )
282  {
283  if ( m_pest_map_twin[ t + x ] > 0.0 )
284  {
285  double l_amount = m_pest_map_twin[ t + x ];
286  for ( unsigned int i=0; i<m_diffusion_mask[m_wind].size(); i++ )
287  {
288  // This adds the pesticide to the main map - simply adds the calculated amount.
290  m_pest_map_height,m_diffusion_mask[m_wind][i]->GetFraction() *l_amount, a_cover, a_ppp);
291  }
292  }
293  }
294  }
295 }
void DiffusionSprayPixel(int a_x, int a_limit_x, int a_y, int a_limit_y, double a_amount, double a_cover, PlantProtectionProducts a_ppp)
Definition: pesticide.cpp:301

References DiffusionSprayPixel(), m_diffusion_mask, m_pest_map_height, m_pest_map_twin, m_pest_map_width, and m_wind.

Referenced by DailyQueueProcess().

◆ TwinMapSpray()

void Pesticide::TwinMapSpray ( LE a_element_spryaed,
double  a_amount,
int  a_minx,
int  a_miny,
int  a_maxx,
int  a_maxy 
)
protected

This is where the initial pesticide concentration is applied to the map. A twin of the real maps is used for spraying the amount of pesticide that is sprayed over each cell and then copied to the real one by using a 'diffusion' process to spread it out to all surrounding cells for drift.

Going through the whole landscape is very slow and unnecessary for small polygons. Since our polygons do not extend beyond the edge of the map ie do not wrap round, then we only need a measure of minx, maxx, miny, maxy. This is set up at the start of the simulation.

195 {
205  /* Replaced with more detailed fate code for EFSA June 2014
206  if (l_pest_use_application_rate.value()) {
207  // We are applying a field rate. The actual residue needs to be calculated here
208  double biomass = a_element_sprayed->GetVegBiomass();
209  double cover = a_element_sprayed->GetVegCover();
210  // rate is in mg/m and needs to be converted to mg/kg
211  double residue = (a_amount/(biomass*0.001)) * 0.435855; // g to kg veg // 0.435855 is a specific calculation to obtain the same residue that Joe Crocker used for the scale of use study
212  a_amount = residue * cover;
213  }
214  */
215  double l_fractional_amount = a_amount * m_prop; // m_prop is a constant related to the grid area (i.e. how many squares are in one grid square).
216  int l_large_map_index = a_element_sprayed->GetMapIndex();
217  for ( int y=a_miny; y<=a_maxy; y++ ) {
218  for ( int x=a_minx; x<=a_maxx; x++ ) {
219  if ( m_land->Get( x, y ) == l_large_map_index )
220  {
221  // This adds the l_fractional_amount to the twin map
222  TwinMapSprayPixel( x, y, l_fractional_amount );
223  }
224  }
225  }
227 }
void TwinMapSprayCorrectBorders(void)
Definition: pesticide.cpp:230
void TwinMapSprayPixel(int a_large_map_x, int a_large_map_y, double a_fractional_amount)
Definition: pesticide.h:357
int Get(int a_x, int a_y)
Definition: rastermap.h:81

References RasterMap::Get(), LE::GetMapIndex(), m_land, m_prop, TwinMapSprayCorrectBorders(), and TwinMapSprayPixel().

Referenced by DailyQueueProcess().

◆ TwinMapSprayCorrectBorders()

void Pesticide::TwinMapSprayCorrectBorders ( void  )
protected
231 {
232  if ( m_x_excess ) {
233  for ( unsigned int i=0; i<m_pest_map_width-1; i++ ) {
235  }
236  }
237 
238  if ( m_y_excess ) {
239  unsigned int l_additive = (m_pest_map_height-1)*m_pest_map_width;
240  for ( unsigned int i=0; i<m_pest_map_height-1; i++ ) {
241  m_pest_map_twin[ i + l_additive ] *= m_corr_y;
242  }
243  }
244 
245  if ( m_x_excess && m_y_excess ) {
246  m_pest_map_twin[ m_pest_map_size-1 ] *= (((double)(PEST_GRIDAREA)) / ((double)(m_x_excess*m_y_excess)));
247  }
248 }

References m_corr_x, m_corr_y, m_pest_map_height, m_pest_map_size, m_pest_map_twin, m_pest_map_width, m_x_excess, m_y_excess, and PEST_GRIDAREA.

Referenced by TwinMapSpray().

◆ TwinMapSprayPixel()

void Pesticide::TwinMapSprayPixel ( int  a_large_map_x,
int  a_large_map_y,
double  a_fractional_amount 
)
inlineprotected
360 {
361  int l_x = a_large_map_x >> PEST_GRIDSIZE_POW2;
362  int l_y = a_large_map_y >> PEST_GRIDSIZE_POW2;
363 
364  m_pest_map_twin[l_y * m_pest_map_width + l_x] +=
365  a_fractional_amount;
366 }

References m_pest_map_twin, m_pest_map_width, and PEST_GRIDSIZE_POW2.

Referenced by TwinMapSpray().

Member Data Documentation

◆ m_corr_x

double Pesticide::m_corr_x
protected

◆ m_corr_y

double Pesticide::m_corr_y
protected

◆ m_daily_spray_queue

vector<vector <PesticideEvent*> > Pesticide::m_daily_spray_queue
protected

List lists of landscape elements, which was sprayed on a given day. One for each PPP we track.

Referenced by DailyQueueAdd(), DailyQueueClear(), DailyQueueProcess(), and Pesticide().

◆ m_diffusion_mask

Diffusion_mask Pesticide::m_diffusion_mask[4]
protected

Pre-calculated square diffusion map, assuming wind directions (4)
Used after spraying an element in the pesticide map to determine how much of the sprayed material spreads into the surroundings.

Referenced by DiffusionMaskInit(), DiffusionMaskInitTest(), TwinMapDiffusion(), and ~Pesticide().

◆ m_land

RasterMap* Pesticide::m_land
protected

Referenced by Pesticide(), and TwinMapSpray().

◆ m_map

Landscape* Pesticide::m_map
protected

◆ m_NoPPPs

int Pesticide::m_NoPPPs
protected

The number of active PPPs to track.

Referenced by Pesticide(), and Tick().

◆ m_pest_daily_decay_frac

double Pesticide::m_pest_daily_decay_frac
protected

Referenced by MainMapDecay(), Pesticide(), and Tick().

◆ m_pest_daily_decay_frac_Soil

double Pesticide::m_pest_daily_decay_frac_Soil
protected

Referenced by MainMapDecay(), and Pesticide().

◆ m_pest_daily_decay_frac_Veg

double Pesticide::m_pest_daily_decay_frac_Veg
protected

Referenced by MainMapDecay(), and Pesticide().

◆ m_pest_map_height

unsigned int Pesticide::m_pest_map_height
protected

The height of one map in cellsize resolution.

Referenced by Pesticide(), SavePPM(), TwinMapDiffusion(), and TwinMapSprayCorrectBorders().

◆ m_pest_map_main

vector<vector <double> > Pesticide::m_pest_map_main
protected

◆ m_pest_map_size

unsigned int Pesticide::m_pest_map_size
protected

The total size of one map in cellsize resolution.

Referenced by MainMapDecay(), Pesticide(), and TwinMapSprayCorrectBorders().

◆ m_pest_map_twin

double* Pesticide::m_pest_map_twin
protected

◆ m_pest_map_width

unsigned int Pesticide::m_pest_map_width
protected

◆ m_prop

double Pesticide::m_prop
protected

Referenced by Pesticide(), and TwinMapSpray().

◆ m_rainfallcategory

unsigned Pesticide::m_rainfallcategory
protected

Daily rainfall saved here * 100 to use as an index to the Pesticide::m_RainWashoffFactor array - an optimisation to stop repeated calls to Landscape::SupplyRain.

Referenced by MainMapDecay(), and Tick().

◆ m_RainWashoffFactor

double Pesticide::m_RainWashoffFactor[10000]
protected

a structure to hold pre-calculated pesticide rain wash off factor (Rw)

Referenced by CalcRainWashOffFactors(), and MainMapDecay().

◆ m_something_to_decay

bool Pesticide::m_something_to_decay[ppp_foobar]
protected

Speed hack. Only actually run the daily decay routine on the pesticide map if and only if we are sure that there is some pesticide anywhere on the map for us to process.

Cleared daily by MainMapDecay().

Set to true when either adding pesticide to the map, or by the MainMapDecay() method itself, when it finds remains of pesticide anywhere on the pesticide map during its run. One copy is needed for each active PPP

Referenced by DailyQueueProcess(), GetAnythingToDecay(), MainMapDecay(), and Pesticide().

◆ m_wind

int Pesticide::m_wind
protected

◆ m_x_excess

int Pesticide::m_x_excess
protected

◆ m_y_excess

int Pesticide::m_y_excess
protected

The documentation for this class was generated from the following files: